Passed
Push — master ( 25b5f2...76397c )
by EMP
04:47
created

main.js ➔ errorDialog   C

Complexity

Conditions 11

Size

Total Lines 33
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 23
dl 0
loc 33
rs 5.4
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like main.js ➔ errorDialog often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
"use strict";
2
3
sodium.ready.then(function() {
4
5
let isReady = true;
6
7
let vaultPage = -4;
8
const vault = new PostVault(function(ok) {
9
	if (ok) vaultPage = -3;
10
});
11
12
const ae = new AllEars(function(ok) {
13
	if (!ok) {
14
		document.getElementById("greeting").textContent = "Failed loading All-Ears";
15
		return;
16
	}
17
18
	try {
19
		if (localStorage.greeting) {
20
			document.getElementById("greeting").textContent = localStorage.greeting;
21
			document.getElementById("txt_pg").value = localStorage.greeting;
22
		} else {
23
			localStorage.greeting = document.head.querySelector("meta[name='aem.subtitle']").content;
24
			document.getElementById("greeting").textContent = localStorage.greeting;
25
			document.getElementById("txt_pg").value = localStorage.greeting;
26
		}
27
	} catch(e) {
28
		document.getElementById("btn_pg").disabled = true;
29
		document.getElementById("txt_pg").disabled = true;
30
		document.getElementById("txt_pg").className = "ita";
31
		document.getElementById("txt_pg").value = "LocalStorage inaccessible";
32
		document.getElementById("greeting").textContent = document.head.querySelector("meta[name='aem.subtitle']").content;
33
	}
34
35
	document.getElementById("txt_umk").maxLength = "60";
36
});
37
38
function TabState(cur, max, btnDele, btnUpdt) {
39
	this.cur = cur;
40
	this.max = max;
41
	this.btnDele = btnDele;
42
	this.btnUpdt = btnUpdt;
43
}
44
45
const tabs = [
46
	new TabState(0, 0, false, true), // Inbox
47
	new TabState(0, 0, false, false), // Outbx
48
	new TabState(0, 1, true,  false), // Write
49
	new TabState(0, 2, false, false), // Notes
50
	new TabState(0, 2, false, false) // Tools
51
];
52
53
function MsgInfo(msgId, msgType, msgNum) {
54
	this.id = msgId;
55
	this.type = msgType;
56
	this.num = msgNum;
57
}
58
59
let msgDisplay = new MsgInfo(null, null, null);
60
let showHeaders = false;
61
let rowsPerPage = 0;
62
63
let tab = 0;
64
const TAB_INBOX = 0;
65
const TAB_DRBOX = 1;
66
const TAB_WRITE = 2;
67
const TAB_NOTES = 3;
68
const TAB_TOOLS = 4;
69
70
function errorDialog(err, focusAfter) {
71
	if (typeof(err) !== "number" || err < 1) return;
72
73
	let btnDisable = [];
74
	const buttons = document.querySelectorAll("nav > button");
75
	buttons.forEach(function(btn) {
76
		btnDisable.push(btn.disabled);
77
		btn.disabled = true;
78
	});
79
80
	const errMsg = ae.getErrorMessage(err);
81
82
	const dlg = document.querySelector("dialog");
83
	dlg.children[0].style.height = getComputedStyle(document.querySelector("#main1 > div[class='mid']")).height;
84
	dlg.querySelector("h1").textContent = "ERROR " + ((err >= 400) ? err : ("0x" + err.toString(16).padStart(2, "0").toUpperCase()));
85
	dlg.querySelector("p").textContent = (typeof(errMsg) === "string") ? errMsg : errMsg[1];
86
	dlg.show();
87
88
	document.querySelector("dialog > div").onclick = function() {
89
		buttons.forEach(function(btn, i) {btn.disabled = btnDisable[i];});
90
		dlg.close();
91
		if (focusAfter) focusAfter.focus();
92
	};
93
94
	document.onkeyup = function(event) {
95
		document.onkeyup = null;
96
		event.preventDefault();
97
98
		buttons.forEach(function(btn, i) {btn.disabled = btnDisable[i];});
99
		dlg.close();
100
		if (focusAfter) focusAfter.focus();
101
	};
102
}
103
104
/* Reg */
105
document.getElementById("btn_reg").onclick = function() {
106
	document.getElementById("reg_provider").textContent = document.head.querySelector("meta[name='aem.provider']").content? document.head.querySelector("meta[name='aem.provider']").content : document.domain;
107
	document.getElementById("s_entry").hidden = true;
108
	document.getElementById("s_reg").hidden = false;
109
};
110
111
document.getElementById("reg_permit").onchange = function() {
112
	if (!this.reportValidity()) {document.getElementById("reg_expire").textContent = "Enter a valid permit to continue."; return;}
113
114
	const p = sodium.from_base64(this.value + "A", sodium.base64_variants.ORIGINAL_NO_PADDING);
115
	const ts = (BigInt(p[32]))
116
	| (BigInt(p[33]) << 8n)
117
	| (BigInt(p[34]) << 16n)
118
	| (BigInt(p[35]) << 24n)
119
	| (BigInt(p[36]) << 32n)
120
	| (BigInt(p[37] & 3) << 40n);
121
122
	const ms = (ts - (BigInt(Date.now()) - 1735689600000n)) + 1073741824n;
123
	if (ms > 1073741824n) {
124
		document.getElementById("reg_cont").disabled = true;
125
		document.getElementById("reg_expire").textContent = "Invalid permit.";
126
	} else if (ms < 0) {
127
		document.getElementById("reg_cont").disabled = true;
128
		document.getElementById("reg_expire").textContent = "Permit expired.";
129
	} else {
130
		document.getElementById("reg_cont").disabled = false;
131
		document.getElementById("reg_expire").textContent = "Permit expires in " +  (ms / 3600000n) + " hours";
132
	}
133
};
134
135
document.getElementById("reg_cont").onclick = function() {
136
	document.getElementById("div_reg1").hidden = true;
137
	document.getElementById("div_reg2").hidden = false;
138
};
139
140
document.getElementById("btn_reg_rnd").onclick = function() {
141
	document.querySelectorAll("#s_reg select")[0].selectedIndex = Math.floor(Math.random() * 16);
142
	document.querySelectorAll("#s_reg select")[1].selectedIndex = Math.floor(Math.random() * 16);
143
	document.querySelectorAll("#s_reg select")[2].selectedIndex = Math.floor(Math.random() * 16);
144
}
145
146
document.getElementById("btn_reg_gen").onclick = function() {
147
	const uid = document.querySelectorAll("#s_reg select")[0].value + document.querySelectorAll("#s_reg select")[1].value + document.querySelectorAll("#s_reg select")[2].value;
148
	document.getElementById("reg_umk").value = ae.reg_genUmk(uid);
149
	document.getElementById("btn_reg_shw").disabled = false;
150
	document.getElementById("btn_reg_cpy").disabled = false;
151
	document.getElementById("btn_reg_reg").disabled = false;
152
}
153
154
document.getElementById("btn_reg_cpy").onclick = function() {
155
	navigator.clipboard.writeText(document.getElementById("reg_umk").value);
156
}
157
158
document.getElementById("btn_reg_shw").onclick = function() {
159
	if (document.getElementById("btn_reg_shw").textContent === "Show") {
160
		document.getElementById("btn_reg_shw").textContent = "Hide";
161
		document.getElementById("reg_umk").type = "text";
162
	} else {
163
		document.getElementById("btn_reg_shw").textContent = "Show";
164
		document.getElementById("reg_umk").type = "password";
165
	}
166
}
167
168
document.getElementById("btn_reg_reg").onclick = function() {
169
	this.disabled = true;
170
171
	ae.reg_register(document.getElementById("reg_permit").value, document.getElementById("reg_umk").value, function(status) {
172
		if (status == 1) {
173
			document.getElementById("reg_status").textContent = "Registered OK";
174
			document.getElementById("btn_reg_reg").disabled = false;
175
		} else {
176
			document.getElementById("btn_reg_reg").disabled = false;
177
			document.getElementById("reg_status").textContent = "Error: " + status;
178
		}
179
	});
180
}
181
182
/* Main */
183
184
function getCountryFlag(countryCode) {
185
	return (!countryCode || countryCode.length !== 2 || countryCode === "??") ? "❔" : sodium.to_string(new Uint8Array([
186
		240, 159, 135, 166 + countryCode.codePointAt(0) - 65,
187
		240, 159, 135, 166 + countryCode.codePointAt(1) - 65
188
	]));
189
}
190
191
function getClockIcon(d) {
192
	const h24 = d.getUTCHours();
193
	let h12 = (h24 === 0 ? 12 : ((h24 > 12) ? h24 - 12 : h24));
194
195
	const m60 = (d.getUTCMinutes() * 60) + d.getUTCSeconds();
196
	let m30 = 0;
197
	if (m60 <= 900) { // <= 15: round down to this hour
198
		m30 = 0;
199
	} else if (m60 > 900 && m60 < 2700) { // 15..45: round to half-past this hour
200
		m30 = 12;
201
	} else { // >= 45: round up to next hour
202
		h12++;
203
		m30 = 0;
204
	}
205
206
	return String.fromCodePoint((128335 + h12) + m30);
207
}
208
209
function clearDisplay() {
210
	document.getElementById("btn_mnext").disabled = true;
211
	document.getElementById("btn_mprev").disabled = true;
212
	document.getElementById("readmsg_export").hidden = true;
213
214
	const el = document.querySelector("#readmsg_main > img, #readmsg_main > audio, #readmsg_main > video, #readmsg_main > embed, #readmsg_main > iframe");
215
	if (!el) return;
216
	if (el.src) URL.revokeObjectURL(el.src);
217
	el.remove();
218
}
219
220
/*
221
function addMsgFlag(abbr, abbrTitle) {
222
	const parent = document.getElementById("readmsg_flags").children[0];
223
224
	const el = document.createElement("abbr");
225
	el.title = abbrTitle;
226
	el.textContent = abbr;
227
228
	parent.appendChild(document.createTextNode(" "));
229
	parent.appendChild(el);
230
}
231
*/
232
233
function displayFile(isHistory, num, showNext) {
234
	if (num < 0 || num >= ae.getUplMsgCount()) return;
235
236
	const fileType = ae.getUplMsgType(num);
237
	if (!fileType) {
238
		if (isHistory) return;
239
		if (showNext === true) return displayFile(false, num + 1, true);
240
		if (showNext === false) return displayFile(false, num - 1, false);
241
		ae.downloadUplMsg(num); return;
242
	}
243
244
	clearDisplay();
245
	document.querySelector("article").scroll(0, 0);
246
	document.querySelector("article").setAttribute("data-msgid", ae.getUplMsgId(num));
247
248
	document.getElementById("btn_mdele").disabled = false;
249
	document.getElementById("btn_msave").disabled = false;
250
	document.getElementById("btn_reply").disabled = true;
251
252
	document.getElementById("btn_msave").onclick = function() {ae.downloadUplMsg(num);};
253
254
	document.getElementById("readmsg_info").hidden = true;
255
	document.getElementById("readmsg_dkim").hidden = true;
256
	document.querySelector("#readmsg_main > h1").textContent = ae.getUplMsgTitle(num);
257
258
	msgDisplay = new MsgInfo(ae.getUplMsgId(num), "upl", num);
259
	if (!isHistory) history.pushState({tab: tab, page: tabs[tab].cur, msg: msgDisplay}, null);
260
261
	document.getElementById("main2").hidden = false;
262
	document.getElementById("main1").hidden = !window.matchMedia("(min-width: 80em)").matches;
263
264
	document.getElementById("btn_mnext").disabled = (num === ae.getUplMsgCount() - 1);
265
	document.getElementById("btn_mprev").disabled = (num === 0);
266
	document.getElementById("btn_mnext").onclick = function() {displayFile(false, num + 1, true);};
267
	document.getElementById("btn_mprev").onclick = function() {displayFile(false, num - 1, false);};
268
269
	if (fileType === "text") {
270
		document.querySelector("#readmsg_main > pre").hidden = false;
271
		try {
272
			document.querySelector("#readmsg_main > pre").textContent = sodium.to_string(ae.getUplMsgBody(num));
273
		} catch(e) {
274
			document.querySelector("#readmsg_main > pre").textContent = "Failed decoding body: " + e.message;
275
		}
276
		return;
277
	}
278
279
	document.querySelector("#readmsg_main > pre").hidden = true;
280
	let el;
281
282
	switch (fileType) {
283
		case "image": {
284
			el = document.createElement("img");
285
			el.src = URL.createObjectURL(new Blob([ae.getUplMsgBody(num).buffer]));
286
			el.onclick = function() {
287
				if (!document.fullscreen)
288
					this.requestFullscreen();
289
				else
290
					document.exitFullscreen();
291
			};
292
		break;}
293
294
		case "audio":
295
		case "video": {
296
			el = document.createElement(fileType);
297
			el.controls = "controls";
298
			el.src = URL.createObjectURL(new Blob([ae.getUplMsgBody(num).buffer]));
299
		break;}
300
301
		case "pdf": {
302
			el = document.createElement("embed");
303
			el.type = "application/pdf";
304
			el.src = URL.createObjectURL(new Blob([ae.getUplMsgBody(num).buffer], {type: "application/pdf"}));
305
		break;}
306
307
		case "html": {
308
			el = document.createElement("iframe");
309
			el.allow = "vertical-scroll";
310
			el.sandbox = "";
311
			el.referrerPolicy = "no-referrer";
312
313
			try {
314
				const sanBody = document.createElement("body");
315
				sanBody.setHTML(sodium.to_string(ae.getUplMsgBody(num).buffer), {sanitizer: new Sanitizer({
316
					"allowElements": [
317
						"a","div","p",
318
						"h1","h2","h3","h4","h5","h6",
319
						"em","strong","b","i","u"
320
					],
321
					"allowAttributes": {
322
						"href": ["*"]
323
					}
324
				})});
325
326
				el.srcdoc =
327
				"<!doctype html><html>" +
328
					"<head>" +
329
						"<style>" +
330
							"html, body {background: #080a08; color: #fff; scrollbar-color: #222 #333;}\n" +
331
							"body {opacity:0.55;}\n" +
332
							"body > *:first-child {margin-top: 0; padding-top: 0;}\n" +
333
							"a {color: #fff;}\n" +
334
							"button, input, select, textarea {background: #000; color: #fff;}\n" +
335
						"</style>" +
336
					"</head>" +
337
					sanBody.outerHTML +
338
				"</html>";
339
			} catch(e) {
340
				el.srcdoc = "<!doctype html><html><head><style>body {background: #080a08; color: #fff; opacity:0.55;} h1 {margin: 0;}</style><body><h1>Error</h1><p>" + e.message + "</p></body></html>";
341
			}
342
		break;}
343
344
		case "svg": {
345
			el = document.createElement("iframe");
346
			el.allow = "";
347
			el.sandbox = "";
348
			el.referrerPolicy = "no-referrer";
349
			el.srcdoc = "<!doctype><html><head><style>body,html,svg {margin: 0; padding: 0; border: 0; height: 100%; width: 100%; display: block; background: #080a08;}</style></head><body>" + sodium.to_string(ae.getUplMsgBody(num).buffer) + "</body></html>";
350
		break;}
351
352
		default: return;
353
	}
354
355
	document.getElementById("readmsg_main").appendChild(el);
356
}
357
358
function displayMsg(isHistory, isInt, num) {
359
	clearDisplay();
360
	document.getElementById("btn_mdele").disabled = false;
361
362
	document.querySelector("article").scroll(0, 0);
363
	document.querySelector("article").setAttribute("data-msgid", isInt? ae.getIntMsgId(num) : ae.getExtMsgId(num));
364
365
	document.getElementById("btn_msave").disabled = false;
366
	document.getElementById("btn_msave").onclick = function() {displayExport(false, isInt, num);};
367
368
	const ts = isInt? ae.getIntMsgTime(num) : ae.getExtMsgTime(num);
369
370
	if (!isInt || ae.getIntMsgType(num) !== "system") {
371
		document.getElementById("btn_reply").disabled = false;
372
373
		document.getElementById("btn_reply").onclick = function() {
374
			document.getElementById("write_recv").value = isInt? ae.getIntMsgFrom(num) : ae.getExtMsgReplyAddress(num);
375
			document.getElementById("write_subj").value = isInt? ae.getIntMsgTitle(num) : ae.getExtMsgTitle(num);
376
			if (!document.getElementById("write_subj").value.startsWith("Re:")) document.getElementById("write_subj").value = "Re: " + document.getElementById("write_subj").value;
377
			document.querySelector("#write2_ask > input").value = isInt? ae.getIntMsgAsk(num) : "";
378
379
			document.getElementById("write_recv").readOnly = !isInt;
380
			document.getElementById("write_subj").readOnly = !isInt;
381
			document.getElementById("write_subj").setAttribute("data-replyid", isInt? "" : ae.getExtMsgHdrId(num));
382
383
			tabs[TAB_WRITE].cur = 0;
384
			document.getElementById("btn_write").disabled = false;
385
			document.getElementById("btn_write").click();
386
			document.getElementById("write_body").focus();
387
388
			for (const opt of document.getElementById("write_from").options) {
389
				if (opt.value === (isInt ? ae.getIntMsgTo(num) : ae.getExtMsgEnvTo(num).split("@")[0].toLowerCase())) {
390
					opt.selected = true;
391
				}
392
			}
393
		};
394
	} else {
395
		document.getElementById("btn_reply").disabled = true;
396
	}
397
398
	document.getElementById("readmsg_info").hidden = false;
399
	document.querySelector("#readmsg_main > pre").hidden = false;
400
401
	document.getElementById("readmsg_envto").textContent = isInt ? "" : ae.getExtMsgEnvTo(num);
402
	document.getElementById("readmsg_hdrto").textContent = isInt ? ae.getIntMsgTo(num) : (ae.getExtMsgHdrTo(num));
403
	if(!isInt && ae.getExtMsgDnTo(num)) {
404
		const span = document.createElement("span");
405
		span.className = "sans";
406
		span.textContent = " • " + ae.getExtMsgDnTo(num);
407
		document.getElementById("readmsg_hdrto").appendChild(span);
408
	}
409
410
	const tzOs = new Date().getTimezoneOffset();
411
	const msgDate = new Date((Number(ts)) + (tzOs * -60000));
412
	document.getElementById("readmsg_date").children[0].textContent = getClockIcon(msgDate);
413
	document.getElementById("readmsg_date").children[1].dateTime = new Date(Number(ts)).toISOString();
414
415
	if (isInt) {
416
		document.getElementById("readmsg_dkim").hidden = true;
417
418
		document.querySelector("#readmsg_main > h1").textContent = ae.getIntMsgTitle(num);
419
		document.querySelector("#readmsg_main > pre").textContent = ae.getIntMsgBody(num);
420
421
		document.getElementById("readmsg_date").children[1].textContent = msgDate.toISOString().slice(0, 19).replace("T", " ");
422
423
		document.getElementById("readmsg_ip").style.visibility = "hidden";
424
		document.getElementById("readmsg_rdns").style.visibility = "hidden";
425
		document.getElementById("readmsg_greet").style.visibility = "hidden";
426
		document.getElementById("readmsg_cert").style.visibility = "hidden";
427
		document.getElementById("readmsg_envfrom").style.visibility = "hidden";
428
		document.getElementById("readmsg_envto").style.visibility = "hidden";
429
430
		if (ae.getIntMsgType(num) !== "system") {
431
			document.getElementById("readmsg_tls").style.visibility = "visible";
432
			document.getElementById("readmsg_tls").children[0].textContent = ae.getIntMsgAsk(num);
433
		} else document.getElementById("readmsg_tls").style.visibility = "hidden";
434
435
		let symbol = document.createElement("span");
436
		switch(ae.getIntMsgType(num)) {
437
			case "system": symbol.title = "System message"; symbol.textContent = "⚙️"; break;
438
			case "public": symbol.title = "Public announcement"; symbol.textContent = "📢"; break;
439
			case "e2ee": symbol.title = "End-to-end encrypted message"; symbol.textContent = "🔒"; break;
440
			case "plain": symbol.title = "Plain message"; symbol.textContent = "-"; break;
441
			default: symbol.title = "Unrecognized type: " + ae.getIntMsgType(num); symbol.textContent = "?";
442
		}
443
444
		document.getElementById("readmsg_hdrfrom").replaceChildren(symbol, document.createTextNode(" " + ae.getIntMsgFrom(num)));
445
	} else {
446
		const headers = document.createElement("p");
447
		headers.textContent = ae.getExtMsgHeaders(num);
448
		headers.className = "mono";
449
		headers.hidden = !showHeaders;
450
451
		const body = document.createElement("p");
452
		body.innerHTML = ae.getExtMsgBody(num, false);
453
454
		document.querySelector("#readmsg_main > pre").replaceChildren(headers, body);
455
456
		const h1 = document.querySelector("#readmsg_main > h1");
457
		h1.textContent = ae.getExtMsgTitle(num);
458
		h1.style.cursor = headers.textContent? "pointer" : "";
459
		h1.onclick = function() {
460
			if (!headers.textContent) return;
461
			showHeaders = !showHeaders;
462
			headers.hidden = !showHeaders;
463
		};
464
465
		let hdrSecs = Math.abs(ae.getExtMsgHdrTime(num));
466
		let hdrTime = "";
467
		if (hdrSecs >= 3600) {
468
			const hdrHours = Math.floor(hdrSecs / 3600);
469
			hdrTime += hdrHours.toString() + "h ";
470
			hdrSecs -= hdrHours * 3600;
471
		}
472
		if (hdrSecs >= 60) {
473
			const hdrMins = Math.floor(hdrSecs / 60);
474
			hdrTime += hdrMins.toString() + "m ";
475
			hdrSecs -= hdrMins * 60;
476
		}
477
		hdrTime += hdrSecs + "s";
478
479
		const hdrTz = (ae.getExtMsgHdrTz(num) >= 0 ? "+" : "-") + Math.floor(Math.abs(ae.getExtMsgHdrTz(num)) / 60).toString().padStart(2, "0") + (Math.abs(ae.getExtMsgHdrTz(num)) % 60).toString().padStart(2, "0");
480
481
		let spans = [document.createElement("span"), document.createElement("span"), document.createElement("span")];
482
		spans[0].textContent = msgDate.toISOString().slice(0, 19).replace("T", " ");
483
		spans[1].className = "sans";
484
		spans[1].textContent = " • ";
485
		spans[2].textContent = hdrTz + " " + ((ae.getExtMsgHdrTime(num) >= 0) ? "+" : "-") + hdrTime;
486
		document.getElementById("readmsg_date").children[1].replaceChildren(...spans);
487
488
		document.getElementById("readmsg_ip").style.visibility = "visible";
489
		document.getElementById("readmsg_rdns").style.visibility = "visible";
490
		document.getElementById("readmsg_greet").style.visibility = "visible";
491
		document.getElementById("readmsg_tls").style.visibility = "visible";
492
		document.getElementById("readmsg_cert").style.visibility = "visible";
493
		document.getElementById("readmsg_envfrom").style.visibility = "visible";
494
		document.getElementById("readmsg_envto").style.visibility = "visible";
495
496
		// DKIM
497
		if (ae.getExtMsgDkimCount(num) > 0) {
498
			document.getElementById("readmsg_dkim").hidden = false;
499
500
			document.querySelectorAll("#readmsg_dkim div").forEach(function(d, i) {
501
				if (i >= ae.getExtMsgDkimCount(num)) {
502
					d.textContent = "";
503
					return;
504
				}
505
				d.textContent = (ae.getExtMsgDkimValidSig(num, i) ? "OK" : "❌") + " " + ae.getExtMsgDkimAlgo(num, i) + " " + ae.getExtMsgDkimHeadHash(num, i) + "/" + ae.getExtMsgDkimBodyHash(num, i) + ": "
506
					+ (ae.getExtMsgDkimIdentity(num, i) ? (ae.getExtMsgDkimIdentity(num, i) + "|") : "") + ae.getExtMsgDkimDomain(num, i) + "|" + ae.getExtMsgDkimSelector(num, i)
507
					+ ((ae.getExtMsgDkimTs(num, i) > 0) ? (" @" + ae.getExtMsgDkimTs(num, i)) : "");
508
			});
509
		} else {
510
			document.getElementById("readmsg_dkim").hidden = true;
511
		}
512
513
		// Left side
514
		document.getElementById("readmsg_country").textContent = getCountryFlag(ae.getExtMsgCcode(num));
515
		document.getElementById("readmsg_country").title = ae.getExtMsgCname(num);
516
		document.getElementById("readmsg_ip").children[1].textContent = ae.getExtMsgIp(num) + (ae.getExtMsgFlagIpBl(num) ? " ❗" : "");
517
		document.getElementById("readmsg_ip").children[2].textContent = " • " + ae.getExtMsgAuSys(num);
518
		document.getElementById("readmsg_tls").children[0].textContent = ae.getExtMsgTLS(num);
519
520
		// Right side
521
		document.getElementById("readmsg_greet").children[0].textContent = ae.getExtMsgGreet(num) + (ae.getExtMsgFlagGrDm(num) ? " ✓" : "");
522
		document.getElementById("readmsg_rdns").children[0].textContent = ae.getExtMsgRdns(num) + (ae.getExtMsgGreet(num).toLowerCase() === ae.getExtMsgRdns(num).toLowerCase() ? " ✓" : "");
523
		document.getElementById("readmsg_cert").children[0].textContent = ae.getExtMsgTlsDomain(num) ? (ae.getExtMsgTlsDomain(num) + " ✓") : "";
524
		document.getElementById("readmsg_envfrom").textContent = ae.getExtMsgEnvFrom(num);
525
		document.getElementById("readmsg_hdrfrom").textContent = ae.getExtMsgHdrFrom(num);
526
		if (ae.getExtMsgDnFrom(num)) {
527
			const span = document.createElement("span");
528
			span.className = "sans";
529
			span.textContent = " • " + ae.getExtMsgDnFrom(num);
530
			document.getElementById("readmsg_hdrfrom").appendChild(span);
531
		}
532
533
/*
534
		clearMsgFlags();
535
		if (!ae.getExtMsgFlagPExt(num)) addMsgFlag("SMTP", "The sender did not use the Extended (ESMTP) protocol");
536
		if ( ae.getExtMsgFlagRare(num)) addMsgFlag("RARE", "The sender issued unusual command(s)");
537
		if ( ae.getExtMsgFlagFail(num)) addMsgFlag("FAIL", "The sender issued invalid command(s)");
538
		if ( ae.getExtMsgFlagPErr(num)) addMsgFlag("PROT", "The sender violated the protocol");
539
*/
540
	}
541
542
	document.getElementById("readmsg_main").hidden = false;
543
	document.getElementById("main2").hidden = false;
544
	document.getElementById("main1").hidden = !window.matchMedia("(min-width: 80em)").matches;
545
546
	msgDisplay = new MsgInfo(isInt? ae.getIntMsgId(num) : ae.getExtMsgId(num), isInt? "int" : "ext", num);
547
	if (!isHistory) history.pushState({tab: tab, page: tabs[tab].cur, msg: msgDisplay}, null);
548
}
549
550
function displayExport(isHistory, isInt, num) {
551
	clearDisplay();
552
	document.getElementById("readmsg_main").hidden = true;
553
	document.getElementById("readmsg_export").hidden = false;
554
	document.getElementById("btn_msave").blur();
555
	document.getElementById("btn_msave").disabled = true;
556
	document.getElementById("btn_reply").disabled = true;
557
	document.getElementById("btn_mdele").disabled = true;
558
559
//	document.querySelector("#readmsg_export > div:nth-child(1)").onclick = function() {};
560
	document.querySelector("#readmsg_export > div:nth-child(2)").onclick = function() {if (isInt) {ae.downloadIntMsg(num);} else {ae.downloadExtMsg(num);} displayMsg(false, isInt, num);};
561
	document.querySelector("#readmsg_export > div:nth-child(3)").onclick = function() {if (isInt) {ae.htmlIntMsg(num, true);} else {ae.htmlExtMsg(num, true);} displayMsg(false, isInt, num);};
562
	document.querySelector("#readmsg_export > div:nth-child(4)").onclick = function() {if (isInt) {ae.txtIntMsg(num, true);} else {ae.txtExtMsg(num, true);} displayMsg(false, isInt, num);};
563
	document.querySelector("#readmsg_export > div:nth-child(5)").onclick = function() {if (isInt) {ae.printIntMsg(num);} else {ae.printExtMsg(num);} displayMsg(false, isInt, num);};
564
	document.querySelector("#readmsg_export > div:nth-child(6)").onclick = function() {navigator.clipboard.writeText(isInt? ae.txtIntMsg(num, false) : ae.txtExtMsg(num, false)); displayMsg(false, isInt, num);};
565
566
	msgDisplay = new MsgInfo(isInt? ae.getIntMsgId(num) : ae.getExtMsgId(num), isInt? "int_exp" : "ext_exp", num);
567
	if (!isHistory) history.pushState({tab: tab, page: tabs[tab].cur, msg: msgDisplay}, null);
568
}
569
570
function displayOutMsg(isHistory, num) {
571
	clearDisplay();
572
	document.querySelector("article").scroll(0, 0);
573
	document.querySelector("article").setAttribute("data-msgid", ae.getOutMsgId(num));
574
575
	document.getElementById("btn_mdele").disabled = false;
576
	document.getElementById("btn_msave").disabled = true;
577
	document.getElementById("btn_reply").disabled = true;
578
579
	document.getElementById("readmsg_info").hidden = false;
580
	document.querySelector("#readmsg_main > pre").hidden = false;
581
582
	document.querySelector("#readmsg_main > h1").textContent = ae.getOutMsgSubj(num);
583
	document.querySelector("#readmsg_main > pre").textContent = ae.getOutMsgBody(num);
584
585
	document.getElementById("readmsg_hdrto").style.visibility   = "visible";
586
	document.getElementById("readmsg_hdrfrom").style.visibility = "visible";
587
	document.getElementById("readmsg_envto").style.visibility   = "visible";
588
589
	document.getElementById("readmsg_hdrfrom").textContent = ae.getOutMsgFrom(num) + "@" + ae.getDomainEml();
590
591
	document.getElementById("readmsg_envto").textContent = ae.getOutMsgMx(num);
592
	document.getElementById("readmsg_hdrto").textContent = ae.getOutMsgTo(num);
593
594
	const ts = ae.getOutMsgTime(num);
595
	const tzOs = new Date().getTimezoneOffset();
596
	document.getElementById("readmsg_date").children[1].textContent = new Date(Number(ts) + (tzOs * -60000)).toISOString().slice(0, 19).replace("T", " ");
597
598
	const isInt = ae.getOutMsgIsInt(num);
599
	document.getElementById("readmsg_ip").style.visibility    = isInt? "hidden" : "visible";
600
	document.getElementById("readmsg_rdns").style.visibility  = isInt? "hidden" : "visible";
601
	document.getElementById("readmsg_tls").style.visibility   = /*isInt?*/ "hidden" /*: "visible"*/; // TODO
602
	document.getElementById("readmsg_cert").style.visibility  = /*isInt?*/ "hidden" /*: "visible"*/; // TODO
603
	document.getElementById("readmsg_greet").style.visibility = isInt? "hidden" : "visible";
604
	document.getElementById("readmsg_envfrom").style.visibility = isInt? "hidden" : "visible";
605
606
	if (!isInt) {
607
		document.getElementById("readmsg_ip").children[1].textContent = ae.getOutMsgIp(num);
608
		document.getElementById("readmsg_ip").children[2].textContent = " • " + ae.getOutMsgAsn(num);
609
		document.getElementById("readmsg_country").textContent = getCountryFlag(ae.getOutMsgCcode(num));
610
		document.getElementById("readmsg_country").title = ae.getOutMsgCname(num);
611
//		document.getElementById("readmsg_tls").children[0].textContent = ae.getOutMsgTLS(num);
612
		document.getElementById("readmsg_greet").children[0].textContent = ae.getOutMsgGreet(num);
613
		document.getElementById("readmsg_rdns").children[0].textContent = ae.getOutMsgRdns(num);
614
		document.getElementById("readmsg_envfrom").textContent = ae.getOutMsgStatus(num);
615
	}
616
617
//	if ( ae.getOutMsgFlagE2ee(num)) addMsgFlag("E2EE", "End-to-end encrypted");
618
619
	document.getElementById("main2").hidden = false;
620
	document.getElementById("main1").hidden = !window.matchMedia("(min-width: 80em)").matches;
621
622
	msgDisplay = new MsgInfo(ae.getOutMsgId(num), "out", num);
623
	if (!isHistory) history.pushState({tab: tab, page: tabs[tab].cur, msg: msgDisplay}, null);
624
}
625
626
function updateAddressButtons() {
627
	const limitReached = (ae.getAddressCountNormal() + ae.getAddressCountShield() >= 31);
628
	document.getElementById("btn_address_create_normal").disabled = (limitReached || ae.getAddressCountNormal() >= ae.getLimitNormalA(ae.getOwnLevel()));
629
	document.getElementById("btn_address_create_shield").disabled = (limitReached || ae.getAddressCountShield() >= ae.getLimitShieldA(ae.getOwnLevel()));
630
}
631
632
function updateAddressCounts() {
633
	document.querySelector("#tbd_accs > tr > td:nth-child(3)").textContent = ae.getAddressCountNormal();
634
	document.querySelector("#tbd_accs > tr > td:nth-child(4)").textContent = ae.getAddressCountShield();
635
636
	document.getElementById("limit_normal").textContent = (ae.getAddressCountNormal() + "/" + ae.getLimitNormalA(ae.getOwnLevel())).padStart(ae.getLimitNormalA(ae.getOwnLevel()) > 9 ? 5 : 1);
637
	document.getElementById("limit_shield").textContent = (ae.getAddressCountShield() + "/" + ae.getLimitShieldA(ae.getOwnLevel())).padStart(ae.getLimitShieldA(ae.getOwnLevel()) > 9 ? 5 : 1);
638
	document.getElementById("limit_total").textContent = ((ae.getAddressCountNormal() + ae.getAddressCountShield()) + "/" + ae.getAddrPerUser()).padStart(5);
639
640
	updateAddressButtons();
641
//	document.getElementById("getask_result").textContent = ae.getOwnAsk(document.getElementById("getask_addr").value);
642
}
643
644
function addOwnAccount() {
645
	const row = document.getElementById("tbd_accs").insertRow(-1);
646
647
	let cell;
648
	cell = row.insertCell(-1); cell.textContent = ae.uidToName(ae.getOwnUid());
649
	cell = row.insertCell(-1); cell.textContent = Math.round(ae.getTotalMsgBytes() / 1048576); // MiB
650
	cell = row.insertCell(-1); cell.textContent = ae.getAddressCountNormal();
651
	cell = row.insertCell(-1); cell.textContent = ae.getAddressCountShield();
652
653
	cell = row.insertCell(-1);
654
	let btn = document.createElement("button");
655
	btn.type = "button";
656
	btn.textContent = "+";
657
	btn.disabled = true;
658
	cell.appendChild(btn);
659
660
	cell = row.insertCell(-1); cell.textContent = ae.getOwnLevel();
661
662
	cell = row.insertCell(-1);
663
	btn = document.createElement("button");
664
	btn.type = "button";
665
	btn.textContent = "−";
666
	btn.disabled = true;
667
	btn.id = "btn_lowme";
668
	btn.onclick = function() {
669
		const newLevel = parseInt(row.cells[5].textContent, 10) - 1;
670
		ae.Account_Update(ae.getOwnUid(), newLevel, function(error) {
671
			if (error === 0) {
672
				row.cells[5].textContent = newLevel;
673
				if (newLevel === 0) {document.getElementById("btn_lowme").disabled = true;}
674
			} else errorDialog(error);
675
		});
676
	};
677
	cell.appendChild(btn);
678
679
	cell = row.insertCell(-1);
680
	btn = document.createElement("button");
681
	btn.type = "button";
682
	btn.textContent = "X";
683
	btn.disabled = true;
684
	btn.id = "btn_delme";
685
	btn.onclick = function() {
686
		ae.Account_Delete(ae.getOwnUid(), function(error) {
687
			if (error === 0) {
688
				row.remove();
689
				document.getElementById("fs_users").disabled = true;
690
			} else errorDialog(error);
691
		});
692
	};
693
	cell.appendChild(btn);
694
}
695
696
function adjustLevel(uid, level, c) {
697
	const fs = document.getElementById("tbl_accs");
698
	fs.disabled = true;
699
700
	ae.Account_Update(uid, level, function(error) {
701
		fs.disabled = false;
702
703
		if (error === 0) {
704
			c[4].children[0].disabled = (level === 3);
705
			c[5].textContent = level;
706
			c[6].children[0].disabled = (level === 0);
707
		} else errorDialog(error);
708
	});
709
}
710
711
function addMsg(isInt, i) {
712
	const row = document.getElementById("tbl_inbox").insertRow(-1);
713
	row.setAttribute("data-msgid", isInt? ae.getIntMsgId(i) : ae.getExtMsgId(i));
714
715
	const ts = isInt? ae.getIntMsgTime(i) : ae.getExtMsgTime(i);
716
	const el = document.createElement("time");
717
	el.dateTime = new Date(Number(ts)).toISOString();
718
	el.textContent = new Date((Number(ts)) + (new Date().getTimezoneOffset() * -60000)).toISOString().slice(0, 10);
719
	let cell = row.insertCell(-1);
720
	cell.appendChild(el);
721
722
	cell = row.insertCell(-1);
723
	cell.textContent = isInt? ae.getIntMsgTitle(i) : ae.getExtMsgTitle(i);
724
	if (!cell.textContent) cell.textContent = "(fail)";
725
726
	if (isInt) {
727
		cell = row.insertCell(-1);
728
		cell.textContent = ae.getIntMsgFrom(i);
729
		cell.className = (ae.getIntMsgFrom(i).length === 16) ? "mono" : "";
730
	} else {
731
		let from1 = ae.getExtMsgHdrFrom(i);
732
		if (!from1) from1 = ae.getExtMsgEnvFrom(i);
733
		const from2 = from1.substring(from1.indexOf("@") + 1);
734
		cell = row.insertCell(-1);
735
		cell.textContent = from1.substring(0, from1.indexOf("@"));
736
737
		const flag = document.createElement("abbr");
738
		flag.textContent = getCountryFlag(ae.getExtMsgCcode(i));
739
		flag.title = ae.getExtMsgCname(i);
740
741
		const fromText = document.createElement("span");
742
		fromText.textContent = " " + from2;
743
744
		cell = row.insertCell(-1);
745
		cell.appendChild(flag);
746
		cell.appendChild(fromText);
747
	}
748
749
	row.onclick = function() {
750
		displayMsg(false, isInt, i);
751
	};
752
}
753
754
function setRowsPerPage(tbl) {
755
	tbl.replaceChildren();
756
	const row = tbl.insertRow(-1);
757
	const cell = row.insertCell(-1);
758
	cell.textContent = "0";
759
	rowsPerPage = Math.floor(getComputedStyle(tbl).height.replace("px", "") / getComputedStyle(tbl.getElementsByTagName("tr")[0]).height.replace("px", ""));
760
	tbl.replaceChildren();
761
}
762
763
function showInbox() {
764
	const tbl = document.getElementById("tbl_inbox");
765
	if (!document.getElementById("main1").hidden) setRowsPerPage(tbl);
766
767
	const maxExt = ae.getExtMsgCount();
768
	const maxInt = ae.getIntMsgCount();
769
	const loadMore = !ae.haveOldest();
770
771
	if (maxExt + maxInt > 0) {
772
		tabs[TAB_INBOX].max = Math.floor((maxExt + maxInt - (loadMore? 0 : 1)) / rowsPerPage);
773
		document.getElementById("btn_rght").disabled = (tabs[TAB_INBOX].cur >= tabs[TAB_INBOX].max);
774
		tbl.replaceChildren();
775
776
		let skipMsgs = rowsPerPage * tabs[TAB_INBOX].cur;
777
		let numExt = 0;
778
		let numInt = 0;
779
		let numAdd = 0;
780
781
		while (numAdd < rowsPerPage) {
782
			const tsInt = (numInt < maxInt) ? ae.getIntMsgTime(numInt) : -1;
783
			const tsExt = (numExt < maxExt) ? ae.getExtMsgTime(numExt) : -1;
784
			if (tsInt === -1 && tsExt === -1) break;
785
786
			if (tsInt !== -1 && (tsExt === -1 || tsInt > tsExt)) {
787
				if (skipMsgs > 0) skipMsgs--; else {addMsg(true, numInt); numAdd++;}
788
				numInt++;
789
			} else if (tsExt !== -1) {
790
				if (skipMsgs > 0) skipMsgs--; else {addMsg(false, numExt); numAdd++;}
791
				numExt++;
792
			}
793
		}
794
	} else {
795
		tabs[TAB_INBOX].max = 0;
796
	}
797
798
	if (loadMore && tabs[TAB_INBOX].cur >= tabs[TAB_INBOX].max) {
799
		const row = tbl.insertRow(-1);
800
		const cell = row.insertCell(-1);
801
		cell.textContent = "Load more (" + Math.round((ae.getTotalMsgBytes() - ae.getReadyMsgBytes()) / 1024) + " KiB left)";
802
803
		row.onclick = function() {
804
			tbl.style.opacity = 0.5;
805
806
			ae.Message_Browse(false, false, function(errorBrowse) {
807
				tbl.style.opacity = 1;
808
809
				if (errorBrowse !== 0) {
810
					errorDialog(errorBrowse);
811
					return;
812
				}
813
814
				showInbox();
815
			});
816
		};
817
	}
818
}
819
820
function showDrbox() {
821
	const tbl = document.getElementById("tbl_drbox");
822
	if (!document.getElementById("main1").hidden) setRowsPerPage(tbl);
823
824
	const drCount = ae.getOutMsgCount();
825
	const loadMore = ae.getReadyMsgBytes() < ae.getTotalMsgBytes();
826
827
	if (drCount > 0) {
828
		tabs[TAB_DRBOX].max = Math.floor((drCount - (loadMore? 0 : 1)) / rowsPerPage);
829
		document.getElementById("btn_rght").disabled = (tabs[TAB_DRBOX].cur >= tabs[TAB_DRBOX].max);
830
		tbl.replaceChildren();
831
832
		let skipMsgs = rowsPerPage * tabs[TAB_DRBOX].cur;
833
		let numAdd = 0;
834
835
		for (let i = 0; numAdd < rowsPerPage && i < drCount; i++) {
836
			if (skipMsgs > 0) {
837
				skipMsgs--;
838
				continue;
839
			}
840
841
			const row = tbl.insertRow(-1);
842
			row.setAttribute("data-msgid", ae.getOutMsgId(i));
843
844
			let cell;
845
			cell = row.insertCell(-1); cell.textContent = new Date(Number(ae.getOutMsgTime(i))).toISOString().slice(0, 10);
846
			cell = row.insertCell(-1); cell.textContent = ae.getOutMsgSubj(i);
847
			row.onclick = function() {displayOutMsg(false, i);};
848
849
			numAdd++;
850
		}
851
	} else {
852
		tabs[TAB_DRBOX].max = 0;
853
	}
854
855
	if (loadMore && tabs[TAB_DRBOX].cur >= tabs[TAB_DRBOX].max) {
856
		const row = tbl.insertRow(-1);
857
		const cell = row.insertCell(-1);
858
		cell.textContent = "Load more (" + Math.round((ae.getTotalMsgBytes() - ae.getReadyMsgBytes()) / 1024) + " KiB left)";
859
860
		row.onclick = function() {
861
			tbl.style.opacity = 0.5;
862
863
			ae.Message_Browse(false, false, function(errorBrowse) {
864
				tbl.style.opacity = 1;
865
866
				if (errorBrowse !== 0) {
867
					errorDialog(errorBrowse);
868
					return;
869
				}
870
871
				showDrbox();
872
			});
873
		};
874
	}
875
}
876
877
function showFiles() {
878
	const tbl = document.getElementById("tbl_files");
879
	if (!document.getElementById("main1").hidden) setRowsPerPage(tbl);
880
881
	const msgCount = ae.getUplMsgCount() + ((vaultPage >= 0) ? vault.getTotalFiles() : 0);
882
	const loadMore = ae.getReadyMsgBytes() < ae.getTotalMsgBytes();
883
884
	if (msgCount > 0) {
885
		tabs[TAB_NOTES].max = 2 + Math.floor((msgCount - (loadMore? 0 : 1)) / rowsPerPage);
886
		document.getElementById("btn_rght").disabled = (tabs[TAB_NOTES].cur >= tabs[TAB_NOTES].max);
887
		tbl.replaceChildren();
888
889
		let skipMsgs = rowsPerPage * (tabs[TAB_NOTES].cur - 2);
890
		let numAdd = 0;
891
892
		for (let i = 0; numAdd < rowsPerPage && i < ae.getUplMsgCount(); i++) {
893
			if (skipMsgs > 0) {
894
				skipMsgs--;
895
				continue;
896
			}
897
898
			const row = tbl.insertRow(-1);
899
			row.setAttribute("data-msgid", ae.getUplMsgId(i));
900
			row.className = "rowfile";
901
902
			let cell = row.insertCell(-1);
903
			cell.textContent = new Date(Number(ae.getUplMsgTime(i))).toISOString().slice(0, 10);
904
			cell.onclick = function() {displayFile(false, i, null);};
905
906
			cell = row.insertCell(-1);
907
			cell.textContent = (ae.getUplMsgBytes(i) / 1024).toFixed(0).padStart(4, " ");
908
			cell.onclick = function() {displayFile(false, i, null);};
909
910
			cell = row.insertCell(-1);
911
			const parentId = ae.getUplMsgParent(i);
912
			if (typeof(parentId) === "number") {
913
				cell.textContent = ae.getExtMsgTitle(parentId);
914
				cell.onclick = function() {displayMsg(false, false, parentId);};
915
			} else if (parentId === false) {
916
				cell.textContent = "Upload";
917
			} else {
918
				cell.textContent = "Unknown";
919
			}
920
921
			cell = row.insertCell(-1);
922
			cell.textContent = ae.getUplMsgTitle(i);
923
			cell.onclick = function() {displayFile(false, i, null);};
924
925
			cell = row.insertCell(-1);
926
			const btn = document.createElement("button");
927
			btn.setAttribute("data-msgid", ae.getUplMsgId(i));
928
			btn.type = "button";
929
			btn.textContent = "X";
930
			btn.onclick = function() {
931
				ae.Message_Delete(this.getAttribute("data-msgid"), function(error) {
932
					if (error === 0) showFiles();
933
					else errorDialog(error);
934
				});
935
			};
936
			cell.appendChild(btn);
937
938
			numAdd++;
939
		}
940
941
		if (vaultPage >= 0) {
942
			for (let i = 0; numAdd < rowsPerPage && i < 256; i++) {
943
				if (vault.getFileSize(i) < 1) continue;
944
945
				if (skipMsgs > 0) {
946
					skipMsgs--;
947
					continue;
948
				}
949
950
				const row = tbl.insertRow(-1);
951
				row.className = "rowfile";
952
953
				let cell = row.insertCell(-1);
954
				cell.textContent = new Date(vault.getFileTime(i) * 1000).toISOString().slice(0, 10);
955
956
				cell = row.insertCell(-1);
957
				cell.textContent = (vault.getFileSize(i) / 1024).toFixed(0).padStart(4, " ");
958
959
				cell = row.insertCell(-1);
960
				cell.textContent = "Vault";
961
962
				cell = row.insertCell(-1);
963
				cell.textContent = vault.getFilePath(i);
964
				cell.onclick = function() {vault.downloadFile(i, function(m,p){}, function(msg) {
965
					if (msg !== "Done") errorDialog(404);
966
				});};
967
968
				cell = row.insertCell(-1);
969
				const btn = document.createElement("button");
970
				btn.type = "button";
971
				btn.textContent = "X";
972
				btn.onclick = function() {
973
					vault.deleteFile(i, function(error) {
974
						if (error === 0) showFiles();
975
						else errorDialog(error);
976
					});
977
				};
978
				cell.appendChild(btn);
979
980
				numAdd++;
981
			}
982
		}
983
	} else tabs[TAB_NOTES].max = 2;
984
985
	if (loadMore && tabs[TAB_NOTES].cur >= tabs[TAB_NOTES].max) {
986
		const row = tbl.insertRow(-1);
987
		row.className = "rowfilex";
988
989
		let cell = row.insertCell(-1);
990
		if (ae.getReadyMsgBytes() < ae.getTotalMsgBytes()) {
991
			cell.textContent = "Load more (" + Math.round((ae.getTotalMsgBytes() - ae.getReadyMsgBytes()) / 1024) + " KiB left)";
992
			cell.onclick = function() {
993
				tbl.style.opacity = 0.5;
994
995
				ae.Message_Browse(false, false, function(errorBrowse) {
996
					tbl.style.opacity = 1;
997
998
					if (errorBrowse !== 0) {
999
						errorDialog(errorBrowse);
1000
						return;
1001
					}
1002
1003
					showFiles();
1004
				});
1005
			};
1006
		}
1007
1008
		cell = row.insertCell(-1);
1009
	}
1010
}
1011
1012
function addAccountToTable(i) {
1013
	if (ae.getOwnUid() === ae.admin_getUserUid(i)) return;
1014
1015
	const row = document.getElementById("tbd_accs").insertRow(-1);
1016
	let cell;
1017
	cell = row.insertCell(-1); cell.textContent = ae.uidToName(ae.admin_getUserUid(i));
1018
	cell = row.insertCell(-1); cell.textContent = Math.round(ae.admin_getUserKib(i) / 1024);
1019
	cell = row.insertCell(-1); cell.textContent = ae.admin_getUserNrm(i);
1020
	cell = row.insertCell(-1); cell.textContent = ae.admin_getUserShd(i);
1021
1022
	cell = row.insertCell(-1);
1023
	let btn = document.createElement("button");
1024
	btn.type = "button";
1025
	btn.textContent = "+";
1026
	btn.disabled = (ae.admin_getUserLvl(i) === 3);
1027
	btn.onclick = function() {const c = this.parentElement.parentElement.cells; adjustLevel(ae.admin_getUserUid(i), ae.admin_getUserLvl(i) + 1, c);};
1028
	cell.appendChild(btn);
1029
1030
	cell = row.insertCell(-1); cell.textContent = ae.admin_getUserLvl(i);
1031
1032
	cell = row.insertCell(-1);
1033
	btn = document.createElement("button");
1034
	btn.type = "button";
1035
	btn.textContent = "−";
1036
	btn.disabled = (ae.admin_getUserLvl(i) === 0);
1037
	btn.onclick = function() {const c = this.parentElement.parentElement.cells; adjustLevel(ae.admin_getUserUid(i), ae.admin_getUserLvl(i) - 1, c);};
1038
	cell.appendChild(btn);
1039
1040
	cell = row.insertCell(-1);
1041
	btn = document.createElement("button");
1042
	btn.type = "button";
1043
	btn.textContent = "X";
1044
	btn.onclick = function() {
1045
		const tr = this.parentElement.parentElement;
1046
		ae.Account_Delete(ae.admin_getUserUid(i), function(error) {
1047
			if (error === 0) tr.remove(); else errorDialog(error);
1048
		});
1049
	};
1050
	cell.appendChild(btn);
1051
}
1052
1053
function updateLimits() {
1054
	const tbl = document.querySelector("#tbl_limits > tbody");
1055
1056
	if (ae.isUserAdmin()) {
1057
		for (let i = 0; i < 4; i++) {
1058
			tbl.rows[i].cells[1].children[0].value = ae.getLimitStorage(i);
1059
			tbl.rows[i].cells[2].children[0].value = ae.getLimitNormalA(i);
1060
			tbl.rows[i].cells[3].children[0].value = ae.getLimitShieldA(i);
1061
		}
1062
	} else {
1063
		const lvl = ae.getOwnLevel();
1064
		tbl.rows[lvl].cells[1].children[0].value = ae.getLimitStorage(lvl);
1065
		tbl.rows[lvl].cells[2].children[0].value = ae.getLimitNormalA(lvl);
1066
		tbl.rows[lvl].cells[3].children[0].value = ae.getLimitShieldA(lvl);
1067
	}
1068
}
1069
1070
function deleteAddress(addr) {
1071
	const buttons = document.querySelectorAll("#tbl_addrs button");
1072
	buttons.forEach(function(btn) {btn.disabled = true;});
1073
1074
	let addressToDelete = -1;
1075
	for (let i = 0; i < ae.getAddressCount(); i++) {
1076
		if (addr === ae.getAddress(i)) {
1077
			addressToDelete = i;
1078
			break;
1079
		}
1080
	}
1081
1082
	if (addressToDelete === -1) return;
1083
1084
	ae.Address_Delete(addressToDelete, function(error1) {
1085
		if (error1 !== 0) {
1086
			buttons.forEach(function(btn) {btn.disabled = false;});
1087
			errorDialog(error1);
1088
			return;
1089
		}
1090
1091
		document.getElementById("tbl_addrs").deleteRow(addressToDelete);
1092
		document.getElementById("write_from").remove(addressToDelete);
1093
1094
		updateAddressCounts();
1095
1096
		ae.Private_Update(function(error2) {
1097
			buttons.forEach(function(btn) {btn.disabled = false;});
1098
			if (error2) errorDialog(error2);
1099
		});
1100
	});
1101
}
1102
1103
function setTab(isHistory, tabNum, pageNum) {
1104
	tab = tabNum;
1105
	if (pageNum !== -1) tabs[tab].cur = pageNum;
1106
1107
	document.querySelectorAll("#main1 > nav:first-of-type > button").forEach(function(btn, i) {
1108
		document.querySelectorAll("#main1 > .mid > div")[i].hidden = (tab !== i);
1109
		btn.disabled = (tab === i);
1110
	});
1111
1112
	const bigScreen = window.matchMedia("(min-width: 80em)").matches;
1113
	document.getElementById("main2").hidden = !bigScreen;
1114
	document.getElementById("btn_leave").disabled = bigScreen;
1115
1116
	switch (tab) {
1117
		case TAB_INBOX: showInbox(); break;
1118
		case TAB_DRBOX: showDrbox(); break;
1119
1120
		case TAB_WRITE:
1121
			if (tabs[tab].cur === 0) {
1122
				document.getElementById("div_write_1").hidden = false;
1123
				document.getElementById("div_write_2").hidden = true;
1124
				document.getElementById("write_recv").focus();
1125
			} else if (!writeVerify()) {
1126
				tabs[TAB_WRITE].cur = 0;
1127
				return;
1128
			}
1129
		break;
1130
1131
		case TAB_NOTES:
1132
			if (vaultPage === -2) {
1133
				vaultPage = -1;
1134
1135
				vault.downloadIndex(function(err) {
1136
					if (err === 0) {
1137
						vaultPage = 0;
1138
					}
1139
				});
1140
			}
1141
1142
			switch (tabs[tab].cur) {
1143
				case 0:
1144
					document.getElementById("div_notes").children[0].hidden = false;
1145
					document.getElementById("div_notes").children[1].hidden = true;
1146
					document.getElementById("div_notes").children[2].hidden = true;
1147
				break;
1148
1149
				case 1:
1150
					document.getElementById("div_notes").children[0].hidden = true;
1151
					document.getElementById("div_notes").children[1].hidden = false;
1152
					document.getElementById("div_notes").children[2].hidden = true;
1153
1154
					document.querySelector("#div_notepad meter").value = ae.getPrivateExtraSpace() / ae.getPrivateExtraSpaceMax();
1155
				break;
1156
1157
				case 2:
1158
					document.getElementById("div_notes").children[0].hidden = true;
1159
					document.getElementById("div_notes").children[1].hidden = true;
1160
					document.getElementById("div_notes").children[2].hidden = false;
1161
1162
				default:
1163
					showFiles();
1164
			}
1165
		break;
1166
1167
		case TAB_TOOLS:
1168
			for (let i = 0; i <= tabs[tab].max; i++) {
1169
				document.getElementById("div_tools").children[i].hidden = (i !== tabs[tab].cur);
1170
			}
1171
		break;
1172
	}
1173
1174
	document.getElementById("btn_dele").disabled = !tabs[tab].btnDele;
1175
	document.getElementById("btn_left").disabled = (tabs[tab].cur === 0);
1176
	document.getElementById("btn_rght").disabled = (tabs[tab].cur === tabs[tab].max);
1177
	document.getElementById("btn_updt").disabled = !tabs[tab].btnUpdt;
1178
1179
	if (!isHistory) history.pushState({tab: tab, page: tabs[tab].cur, msg: msgDisplay}, null);
1180
}
1181
1182
window.onresize = function() {
1183
	setTab(true, tab, tabs[tab].cur);
1184
}
1185
1186
function clearWrite() {
1187
	setTab(false, TAB_WRITE, 0);
1188
1189
	document.querySelector("#write2_ask > input").value = "";
1190
	document.getElementById("write_body").value = "";
1191
	document.getElementById("write_subj").value = "";
1192
	document.getElementById("write_subj").readOnly = false;
1193
	document.getElementById("write_subj").setAttribute("data-replyid", "");
1194
	document.getElementById("write_recv").value = "";
1195
	document.getElementById("write_recv").readOnly = false;
1196
	document.getElementById("write_recv").focus();
1197
}
1198
1199
function refreshContactList() {
1200
	let opts = [];
1201
1202
	for (let i = 0; i < ae.getContactCount(); i++) {
1203
		const el = document.createElement("option");
1204
		el.value = ae.getContactMail(i);
1205
		opts.push(el);
1206
	}
1207
1208
	if (ae.isUserAdmin()) {
1209
		const el = document.createElement("option");
1210
		el.value = "All Users";
1211
		opts.push(el);
1212
	}
1213
1214
	document.getElementById("contact_emails").replaceChildren(...opts);
1215
}
1216
1217
function addContact(mail, name, note) {
1218
	const tbl = document.getElementById("tbl_ctact");
1219
	const row = tbl.insertRow(-1);
1220
1221
	let cell = row.insertCell(-1);
1222
	cell.autocapitalize = "off";
1223
	cell.contentEditable = true;
1224
	cell.inputMode = "email";
1225
	cell.spellcheck = false;
1226
	cell.textContent = mail;
1227
1228
	cell = row.insertCell(-1);
1229
	cell.autocapitalize = "words";
1230
	cell.contentEditable = true;
1231
	cell.spellcheck = false;
1232
	cell.textContent = name;
1233
1234
	cell = row.insertCell(-1);
1235
	cell.autocapitalize = "off";
1236
	cell.contentEditable = true;
1237
	cell.spellcheck = false;
1238
	cell.textContent = note;
1239
1240
	cell = row.insertCell(-1);
1241
	const el = document.createElement("button");
1242
	el.type = "button";
1243
	el.textContent = "X";
1244
	el.onclick = function() {row.remove();};
1245
	cell.appendChild(el);
1246
}
1247
1248
function addContacts() {
1249
	for (let i = 0; i < ae.getContactCount(); i++) {
1250
		addContact(
1251
			ae.getContactMail(i),
1252
			ae.getContactName(i),
1253
			ae.getContactNote(i)
1254
		);
1255
	}
1256
1257
	refreshContactList();
1258
}
1259
1260
function addAddress(num) {
1261
	const addrTable = document.getElementById("tbl_addrs");
1262
	const row = addrTable.insertRow(-1);
1263
	const addr = ae.getAddress(num);
1264
1265
	let pref = "";
1266
	let counter = 0;
1267
	for (let i = 0; i < ae.getAddressNick(num).length; i++) {
1268
		if (
1269
		    addr[counter] === ae.getAddressNick(num)[i].toLowerCase()
1270
		|| (addr[counter] === '0' && ae.getAddressNick(num)[i].toLowerCase() == 'o')
1271
		|| (addr[counter] === '1' && (ae.getAddressNick(num)[i].toLowerCase() == 'i' || ae.getAddressNick(num)[i].toLowerCase() == 'l'))
1272
		|| (addr[counter] === 'w' && ae.getAddressNick(num)[i].toLowerCase() == 'v')
1273
		) {
1274
			pref += ae.getAddressNick(num)[i].toLowerCase();
1275
			counter++;
1276
		}
1277
	}
1278
	pref += addr.slice(counter);
1279
1280
	let cell = row.insertCell(-1);
1281
	let el = document.createElement("input");
1282
	el.type = "text";
1283
	el.size = ae.isAddressShield(num) ? 16 : 15;
1284
1285
	if (document.getElementById("chk_addr_nick").checked) {
1286
		el.minLength = ae.getAddress(num).length;
1287
		el.maxLength = 31;
1288
		el.placeholder = ae.getAddress(num);
1289
		el.value = ae.getAddressNick(num);
1290
1291
		el.onchange = function() {
1292
			ae.setAddressNick(num, this.value);
1293
		};
1294
	} else {
1295
		el.value = pref;
1296
		el.readOnly = true;
1297
1298
		el.onclick = function() {
1299
			navigator.clipboard.writeText((ae.isAddressShield(num)? ae.shieldMix(el.value, 0) : pref) + "@" + ae.getDomainEml());
1300
		};
1301
	}
1302
1303
	cell.appendChild(el);
1304
1305
	cell = row.insertCell(-1);
1306
	el = document.createElement("input");
1307
	el.type = "checkbox";
1308
	el.checked = ae.getAddressAccInt(num);
1309
	cell.appendChild(el);
1310
1311
	cell = row.insertCell(-1);
1312
	el = document.createElement("input");
1313
	el.type = "checkbox";
1314
	el.checked = ae.getAddressAccExt(num);
1315
	cell.appendChild(el);
1316
1317
	cell = row.insertCell(-1);
1318
	el = document.createElement("input");
1319
	el.type = "checkbox";
1320
	el.checked = ae.getAddressAllVer(num);
1321
	cell.appendChild(el);
1322
1323
	cell = row.insertCell(-1);
1324
	el = document.createElement("input");
1325
	el.type = "checkbox";
1326
	el.checked = ae.getAddressAttach(num);
1327
	cell.appendChild(el);
1328
1329
	cell = row.insertCell(-1);
1330
	el = document.createElement("input");
1331
	el.type = "checkbox";
1332
	el.checked = ae.getAddressSecure(num);
1333
	cell.appendChild(el);
1334
1335
	cell = row.insertCell(-1);
1336
	el = document.createElement("input");
1337
	el.type = "checkbox";
1338
	el.checked = ae.getAddressOrigin(num);
1339
	cell.appendChild(el);
1340
1341
	cell = row.insertCell(-1);
1342
	el = document.createElement("button");
1343
	el.type = "button";
1344
	el.textContent = "X";
1345
	el.onclick = function() {deleteAddress(addr);};
1346
	cell.appendChild(el);
1347
1348
	el = document.createElement("option");
1349
	el.value = pref;
1350
	el.textContent = pref + "@" + ae.getDomainEml();
1351
	document.getElementById("write_from").appendChild(el);
1352
}
1353
1354
function addAddresses() {
1355
	const si = Math.max(0, document.getElementById("write_from").selectedIndex);
1356
1357
	document.getElementById("tbl_addrs").replaceChildren();
1358
	document.getElementById("write_from").replaceChildren();
1359
1360
	for (let i = 0; i < ae.getAddressCount(); i++) {
1361
		addAddress(i);
1362
	}
1363
1364
	document.getElementById("write_from").selectedIndex = si;
1365
}
1366
1367
function addressCreate(addr) {
1368
	document.getElementById("btn_address_create_normal").disabled = true;
1369
	document.getElementById("btn_address_create_shield").disabled = true;
1370
1371
	ae.Address_Create(addr, function(error1) {
1372
		if (error1 !== 0) {
1373
			updateAddressButtons();
1374
			errorDialog(error1, (addr !== "SHIELD") ? document.getElementById("txt_address_create_normal") : null);
1375
			return;
1376
		}
1377
1378
		ae.Private_Update(function(error2) {
1379
			updateAddressCounts();
1380
1381
			addAddress(ae.getAddressCount() - 1);
1382
			if (addr !== "SHIELD") {
1383
				document.getElementById("txt_address_create_normal").value = "";
1384
				document.getElementById("txt_address_create_normal").focus();
1385
			}
1386
1387
			if (error2 !== 0) errorDialog(error2, (addr !== "SHIELD") ? document.getElementById("txt_address_create_normal") : null);
1388
		});
1389
	});
1390
}
1391
1392
function reloadAccount() {
1393
	updateLimits();
1394
	addOwnAccount();
1395
	addContacts();
1396
	addAddresses();
1397
	updateAddressCounts();
1398
1399
	document.getElementById("fs_admin").disabled = !ae.isUserAdmin();
1400
	document.getElementById("txt_notepad").value = ae.getPrivateExtra();
1401
}
1402
1403
function writeVerify() {
1404
	if (
1405
	   !document.getElementById("write_recv").reportValidity()
1406
	|| !document.getElementById("write_subj").reportValidity()
1407
	|| !document.getElementById("write_body").reportValidity()
1408
	) return false;
1409
1410
	document.getElementById("div_write_1").hidden = true;
1411
	document.getElementById("div_write_2").hidden = false;
1412
1413
	document.getElementById("write2_recv").textContent = document.getElementById("write_recv").value;
1414
	document.getElementById("write2_subj").textContent = document.getElementById("write_subj").value;
1415
	document.getElementById("write2_rply").textContent = document.getElementById("write_subj").getAttribute("data-replyid");
1416
	document.getElementById("write2_body").textContent = document.getElementById("write_body").value;
1417
1418
	if (document.getElementById("write_recv").value.indexOf("@") >= 0) {
1419
		document.getElementById("write2_from").textContent = document.getElementById("write_from").value + "@" + ae.getDomainEml();
1420
		document.getElementById("write2_ask").hidden = true;
1421
	} else {
1422
		document.getElementById("write2_from").textContent = document.getElementById("write_from").value;
1423
		document.getElementById("write2_ask").hidden = (document.getElementById("write_recv").value === "All Users");
1424
	}
1425
1426
	document.querySelector("#write2_send > button").disabled = false;
1427
	document.getElementById("write2_btntxt").textContent = "Send to";
1428
	return true;
1429
}
1430
1431
// Interface elements
1432
if (window.matchMedia("(prefers-color-scheme: light)").matches) document.querySelector("head > meta[name='theme-color']").content = "#eef";
1433
window.matchMedia("(prefers-color-scheme: light)").onchange = function() {document.querySelector("head > meta[name='theme-color']").content = window.matchMedia("(prefers-color-scheme: light)").matches? "#eef" : "#001";};
1434
1435
window.onpopstate = function(event) {
1436
	if (!isReady || !event.state) return;
1437
	setTab(true, event.state.tab, event.state.page);
1438
	msgDisplay = event.state.msg;
1439
1440
	if (msgDisplay) {
1441
		switch (msgDisplay.type) {
1442
			case "ext": displayMsg(true, false, msgDisplay.num); break;
1443
			case "int": displayMsg(true, true, msgDisplay.num); break;
1444
			case "out": displayOutMsg(true, msgDisplay.num); break;
1445
			case "upl": displayFile(true, msgDisplay.num, null); break;
1446
			case "ext_exp": displayExport(true, false, msgDisplay.num); break;
1447
			case "int_exp": displayExport(true, true, msgDisplay.num); break;
1448
		}
1449
	}
1450
};
1451
1452
document.querySelectorAll("#main1 > nav:first-of-type > button").forEach(function(btn, i) {
1453
	btn.onclick = function() {setTab(false, i, -1);};
1454
});
1455
1456
document.getElementById("btn_left").onclick = function() {
1457
	setTab(false, tab, tabs[tab].cur - 1);
1458
};
1459
1460
document.getElementById("btn_rght").onclick = function() {
1461
	setTab(false, tab, tabs[tab].cur + 1);
1462
};
1463
1464
document.getElementById("btn_dele").onclick = function() {
1465
	this.blur();
1466
1467
	if (tab === TAB_WRITE) clearWrite();
1468
};
1469
1470
document.getElementById("btn_updt").onclick = function() {
1471
	const btn = this;
1472
	btn.disabled = true;
1473
	btn.blur();
1474
1475
	if (tab === TAB_INBOX) {
1476
		document.getElementById("tbl_inbox").style.opacity = 0.5;
1477
1478
		ae.Message_Browse(true, false, function(error) {
1479
			btn.disabled = false;
1480
			document.getElementById("tbl_inbox").style.opacity = 1;
1481
1482
			if (error === 0xAA) {
1483
				showInbox();
1484
			} else {
1485
				errorDialog(error);
1486
			}
1487
		});
1488
	}
1489
};
1490
1491
document.getElementById("btn_mdele").onclick = function() {
1492
	const delId = document.querySelector("article").getAttribute("data-msgid");
1493
	if (!delId) return;
1494
1495
	const btn = this;
1496
	btn.blur();
1497
	btn.disabled = true;
1498
1499
	ae.Message_Delete(delId, function(error) {
1500
		if (error !== 0) {
1501
			btn.disabled = false;
1502
			errorDialog(error);
1503
			return;
1504
		}
1505
1506
		switch (tab) {
1507
			case TAB_INBOX: showInbox(); break;
1508
			case TAB_DRBOX: showDrbox(); break;
1509
			case TAB_NOTES: showFiles(); break;
1510
		}
1511
	});
1512
};
1513
1514
document.getElementById("btn_leave").onclick = function() {
1515
	document.getElementById("main2").hidden = true;
1516
	document.getElementById("main1").hidden = false;
1517
};
1518
1519
document.getElementById("btn_newcontact").onclick = function() {
1520
	addContact("", "", "");
1521
};
1522
1523
document.getElementById("btn_savecontacts").onclick = function() {
1524
	while (ae.getContactCount() > 0) {
1525
		ae.deleteContact(0);
1526
	}
1527
1528
	for (const row of document.getElementById("tbl_ctact").rows) {
1529
		ae.addContact(row.cells[0].textContent, row.cells[1].textContent, row.cells[2].textContent);
1530
	}
1531
1532
	refreshContactList();
1533
1534
	const btn = this;
1535
	btn.disabled = true;
1536
1537
	ae.Private_Update(function(error) {
1538
		btn.disabled = false;
1539
		if (error) errorDialog(error);
1540
	});
1541
};
1542
1543
document.getElementById("chk_addr_nick").onclick = function() {
1544
	addAddresses();
1545
};
1546
1547
document.getElementById("btn_address_create_normal").onclick = function() {
1548
	if (ae.getAddressCountNormal() >= ae.getLimitNormalA(ae.getOwnLevel()) || ae.getAddressCountNormal() + ae.getAddressCountShield() >= 31) return;
1549
1550
	const txtNewAddr = document.getElementById("txt_address_create_normal");
1551
	if (!txtNewAddr.reportValidity()) return;
1552
1553
	addressCreate(txtNewAddr.value.toLowerCase());
1554
};
1555
1556
document.getElementById("txt_address_create_normal").onkeyup = function(event) {
1557
	if (event.key !== "Enter") return;
1558
	event.preventDefault();
1559
	document.getElementById("btn_address_create_normal").click();
1560
};
1561
1562
document.getElementById("btn_address_create_shield").onclick = function() {
1563
	if (ae.getAddressCountShield() >= ae.getLimitShieldA(ae.getOwnLevel()) || ae.getAddressCountNormal() + ae.getAddressCountShield() >= 31) return;
1564
1565
	addressCreate("SHIELD");
1566
};
1567
1568
document.getElementById("btn_address_update").onclick = function() {
1569
	const btn = this;
1570
	btn.disabled = true;
1571
1572
	const rows = document.getElementById("tbl_addrs").rows;
1573
1574
	for (let i = 0; i < rows.length; i++) {
1575
		ae.setAddressAccInt(i, rows[i].getElementsByTagName("input")[1].checked);
1576
		ae.setAddressAccExt(i, rows[i].getElementsByTagName("input")[2].checked);
1577
		ae.setAddressAllVer(i, rows[i].getElementsByTagName("input")[3].checked);
1578
		ae.setAddressAttach(i, rows[i].getElementsByTagName("input")[4].checked);
1579
		ae.setAddressSecure(i, rows[i].getElementsByTagName("input")[5].checked);
1580
		ae.setAddressOrigin(i, rows[i].getElementsByTagName("input")[6].checked);
1581
	}
1582
1583
	ae.Address_Update(function(error) {
1584
		btn.disabled = false;
1585
		if (error) errorDialog(error);
1586
	});
1587
};
1588
1589
1590
document.getElementById("txt_sender").onkeyup = function(event) {
1591
	if (event.key !== "Enter") return;
1592
	event.preventDefault();
1593
	document.getElementById("btn_sender").click();
1594
};
1595
1596
document.getElementById("btn_permit").onclick = function() {
1597
	const btn = this;
1598
	btn.disabled = true;
1599
1600
	ae.Account_Permit(function(error, result) {
1601
		if (error === 0) {
1602
			document.getElementById("txt_permit").value = result;
1603
		} else errorDialog(error);
1604
1605
		btn.disabled = false;
1606
	});
1607
};
1608
1609
document.getElementById("chk_dng_usr").onclick = function() {
1610
	document.getElementById("btn_lowme").disabled = !this.checked || (ae.getOwnLevel() === 0);
1611
	document.getElementById("btn_erame").disabled = !this.checked;
1612
	document.getElementById("btn_delme").disabled = !this.checked;
1613
};
1614
1615
document.getElementById("btn_erame").onclick = function() {
1616
	ae.Message_Delete("ALL", function(error) {
1617
		if (error === 0) {
1618
			document.getElementById("chk_dng_usr").checked = false;
1619
			document.getElementById("chk_dng_usr").onclick();
1620
		} else errorDialog(error);
1621
	});
1622
};
1623
1624
document.getElementById("btn_notepad_restore").onclick = function() {
1625
	document.getElementById("txt_notepad").value = ae.getPrivateExtra();
1626
	document.getElementById("btn_notepad_savepad").disabled = true;
1627
	document.getElementById("txt_notepad").oninput = function() {
1628
		this.oninput = null;
1629
		document.getElementById("btn_notepad_savepad").disabled = false;
1630
		document.getElementById("btn_notepad_savepad").textContent = "Save";
1631
	};
1632
};
1633
1634
document.getElementById("txt_notepad").oninput = function() {
1635
	document.getElementById("btn_notepad_savepad").disabled = false;
1636
};
1637
1638
document.getElementById("btn_notepad_savepad").onclick = function() {
1639
	const btn = this;
1640
	btn.disabled = true;
1641
1642
	const error = ae.setPrivateExtra(document.getElementById("txt_notepad").value);
1643
	if (error !== 0) {
1644
		btn.disabled = false;
1645
		errorDialog(error);
1646
		return;
1647
	}
1648
1649
	ae.Private_Update(function(error2) {
1650
		if (error2 !== 0) {
1651
			btn.disabled = false;
1652
			errorDialog(error2);
1653
		} else {
1654
			document.querySelector("#div_notepad meter").value = ae.getPrivateExtraSpace() / ae.getPrivateExtraSpaceMax();
1655
			btn.textContent = "Saved";
1656
			document.getElementById("txt_notepad").oninput = function() {
1657
				this.oninput = null;
1658
				btn.textContent = "Save";
1659
				btn.disabled = false;
1660
			};
1661
		}
1662
	});
1663
};
1664
1665
document.getElementById("btn_notepad_saveupl").onclick = function() {
1666
	const np = document.getElementById("txt_notepad");
1667
	np.disabled = true;
1668
1669
	let fname = prompt("Save as...", "Untitled");
1670
	if (!fname.endsWith(".txt")) fname += ".txt";
1671
1672
	ae.Message_Upload(fname, np.value, function(error) {
1673
		if (error === 0) {
1674
			np.value = "";
1675
			showFiles();
1676
			document.getElementById("tbd_accs").children[0].children[1].textContent = Math.round(ae.getTotalMsgBytes() / 1024 / 1024);
1677
		} else errorDialog(error);
1678
1679
		np.disabled = false;
1680
	});
1681
};
1682
1683
document.getElementById("btn_upload").onclick = function() {
1684
	const btn = this;
1685
	const fileSelector = document.createElement("input");
1686
	fileSelector.type = "file";
1687
	fileSelector.click();
1688
1689
	fileSelector.onchange = function() {
1690
		btn.disabled = true;
1691
1692
		const reader = new FileReader();
1693
		reader.onload = function() {
1694
			ae.Message_Upload(fileSelector.files[0].name, new Uint8Array(reader.result), function(error) {
1695
				if (error === 0) {
1696
					showFiles();
1697
					document.getElementById("tbd_accs").children[0].children[1].textContent = Math.round(ae.getTotalMsgBytes() / 1024 / 1024);
1698
				} else errorDialog(error);
1699
1700
				btn.disabled = false;
1701
			});
1702
		};
1703
1704
		reader.readAsArrayBuffer(fileSelector.files[0]);
1705
	};
1706
};
1707
1708
document.getElementById("btn_pg").onclick = function() {
1709
//	localStorage.greeting = document.getElementById("txt_pg").value;
1710
};
1711
1712
document.querySelector("#write2_send > button").onclick = function() {
1713
	const btn = this;
1714
	btn.disabled = true;
1715
1716
	let ask = null;
1717
	if (document.getElementById("write2_recv").textContent.indexOf("@") === -1) {
1718
		const elAsk = document.querySelector("#write2_ask > input");
1719
		if (!elAsk.reportValidity()) {
1720
			btn.disabled = false;
1721
			return;
1722
		}
1723
		ask = elAsk.value;
1724
	}
1725
1726
	document.getElementById("write2_btntxt").textContent = "Sending to";
1727
1728
	ae.Message_Create(
1729
		document.getElementById("write_subj").value,
1730
		document.getElementById("write_body").value,
1731
		document.getElementById("write_from").value,
1732
		document.getElementById("write_recv").value,
1733
		document.getElementById("write_subj").getAttribute("data-replyid"),
1734
		ask,
1735
		function(error) {
1736
			if (error !== 0) {
1737
				errorDialog(error);
1738
				document.getElementById("write2_btntxt").textContent = "Retry sending to";
1739
				btn.disabled = false;
1740
				return;
1741
			}
1742
1743
			showDrbox();
1744
			clearWrite();
1745
			displayOutMsg(false, 0);
1746
		}
1747
	);
1748
};
1749
1750
document.getElementById("btn_sender").onclick = function() {
1751
	ae.Message_Sender(document.getElementById("txt_sender_hash").value, Date.parse(document.getElementById("txt_sender_date").value) / 1000, function(error, result) {
1752
		if (error !== 0) {
1753
			errorDialog(error);
1754
			return;
1755
		}
1756
1757
		document.getElementById("txt_sender_res").value = result;
1758
	});
1759
};
1760
1761
document.getElementById("btn_limits").onclick = function() {
1762
	const btn = this;
1763
	btn.disabled = true;
1764
1765
	const mib = [parseInt(document.getElementById("lim_mib0").value, 10), parseInt(document.getElementById("lim_mib1").value, 10), parseInt(document.getElementById("lim_mib2").value, 10), parseInt(document.getElementById("lim_mib3").value, 10)];
1766
	const nrm = [parseInt(document.getElementById("lim_nrm0").value, 10), parseInt(document.getElementById("lim_nrm1").value, 10), parseInt(document.getElementById("lim_nrm2").value, 10), parseInt(document.getElementById("lim_nrm3").value, 10)];
1767
	const shd = [parseInt(document.getElementById("lim_shd0").value, 10), parseInt(document.getElementById("lim_shd1").value, 10), parseInt(document.getElementById("lim_shd2").value, 10), parseInt(document.getElementById("lim_shd3").value, 10)];
1768
1769
	ae.Setting_Limits(mib, nrm, shd, function(error) {
1770
		btn.disabled = false;
1771
1772
		if (error !== 0) {
1773
			errorDialog(error);
1774
		} else {
1775
			updateAddressCounts();
1776
		}
1777
	});
1778
};
1779
1780
document.getElementById("btn_ask").onclick = function() {
1781
	document.getElementById("txt_ask").textContent = ae.getOwnAsk();
1782
};
1783
1784
document.getElementById("txt_umk").onfocus = function() {
1785
//	document.getElementById("greeting").textContent = localStorage.greeting;
1786
};
1787
1788
document.getElementById("txt_umk").onkeyup = function(event) {
1789
	if (event.key !== "Enter") return;
1790
	event.preventDefault();
1791
	document.getElementById("btn_entry").click();
1792
};
1793
1794
document.getElementById("btn_entry").onclick = function() {
1795
	const txtUmk = document.getElementById("txt_umk");
1796
1797
	if (txtUmk.value === "") {
1798
		ae.reset();
1799
		document.getElementById("greeting").textContent = "Data cleared";
1800
		return;
1801
	}
1802
1803
	if (!txtUmk.reportValidity()) return;
1804
1805
	const btn = this;
1806
	btn.disabled = true;
1807
1808
	document.getElementById("txt_umk").disabled = true;
1809
1810
	ae.setKeys(txtUmk.value, function(successSetKeys) {
1811
		if (!successSetKeys) {
1812
			document.getElementById("txt_umk").disabled = false;
1813
			txtUmk.focus();
1814
1815
			document.getElementById("greeting").textContent = "SetKeys failed";
1816
			btn.disabled = false;
1817
			return;
1818
		}
1819
1820
		document.body.style.cursor = "wait";
1821
		document.getElementById("greeting").textContent = "Connecting...";
1822
1823
		if (vaultPage === -3) {
1824
			vault.setKeys(txtUmk.value, function(vaultKeysOk) {
1825
				if (vaultKeysOk) vaultPage = -2;
1826
			});
1827
		}
1828
1829
		ae.Message_Browse(true, true, function(errorBrowse) {
1830
			document.body.style.cursor = "";
1831
1832
			if (errorBrowse === 1025) {
1833
				document.getElementById("greeting").textContent = "Please wait..."
1834
1835
				ae.Account_Keyset(function(status) {
1836
					btn.disabled = false;
1837
					btn.focus();
1838
					document.getElementById("greeting").textContent = (status === true) ? "OK - try again" : "Keyset error: " + status;
1839
					return;
1840
				});
1841
1842
				return;
1843
			} else if (errorBrowse !== 0 && errorBrowse !== 0x09) {
1844
				let errorMsg = ae.getErrorMessage(errorBrowse);
1845
				if (typeof(errorMsg) == "object") errorMsg = errorMsg[1];
1846
1847
				document.getElementById("greeting").textContent = errorMsg + " ("+ ((errorBrowse >= 400) ? errorBrowse : "0x" + errorBrowse.toString(16).padStart(2, "0").toUpperCase()) + ")";
1848
				document.getElementById("txt_umk").disabled = false;
1849
				btn.disabled = false;
1850
				btn.focus();
1851
				return;
1852
			}
1853
1854
			txtUmk.value = "";
1855
			document.getElementById("s_entry").hidden = true;
1856
			document.getElementById("s_main").hidden = false;
1857
			isReady = true;
1858
			reloadAccount();
1859
			history.replaceState({tab: 0, page: 0, msg: msgDisplay}, null);
1860
			setTab(true, 0, 0);
1861
1862
			if (errorBrowse !== 0) errorDialog(errorBrowse);
1863
			if (!ae.isUserAdmin()) return;
1864
1865
			ae.Account_Browse(function(errorAcc) {
1866
				if (errorAcc === 0) {
1867
					for (let i = 0; i < ae.admin_getUserCount(); i++) {addAccountToTable(i);}
1868
					updateLimits();
1869
				} else {
1870
					errorDialog(errorAcc);
1871
				}
1872
			});
1873
		});
1874
	});
1875
};
1876
1877
});
1878